package cn.wolfcode.luowowo.search.service;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.domain.UserInfoTemplate;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.DestinationTemplateRepository;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
public class StrategyServiceImpl implements IStrategySearchService{
    @Autowired
    private StrategyTemplateRepository repository;
    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public void saveOrUpdate(StrategyTemplate strategyTemplate) {
        repository.save(strategyTemplate);
    }

    @Override
    public List<Map<String, Object>> getStrategyThemeTop5() {
        List<Map<String, Object>> list = new ArrayList<>();
        List<StatisVO> vos = queryConditionThemeGroup();
        Map<String, Object> map = null;
        for (StatisVO vo : vos) {
            map = new HashMap<>();
            map.put("theme",vo);
            List<StatisVO> dests = getDests(vo.getId());
            map.put("dests",dests);

            list.add(map);
        }
        //优化三:拿前五
        if(list.size()>5){
            List<Map<String, Object>> list1 = new ArrayList<>();
            for (Map<String, Object> m : list) {
                if(list1.size()>=5){
                    return list1;
                }
                list1.add(m);
            }
        }
        return list;
    }

    @Override
    public List<StatisVO> queryConditionThemeGroup() {
        return statisVOSGroup("themeId","themeName","themeGroup",null);
    }

    @Override
    public List<StatisVO> queryConditionChinasGroup() {
        return statisVOSGroup("provinceId","provinceName","chinasGroup",null);
    }

    @Override
    public List<StatisVO> queryConditionAbroadsGroup() {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery("countryId", 1));
        return statisVOSGroup("countryId","countryName","countryGroup",boolQueryBuilder);
    }

    @Override
    public Page query(SearchQueryObject qo) {
        PageRequest pageRequest = PageRequest.of(qo.getCurrentPage() - 1,
                qo.getPageSize(),
                Sort.Direction.DESC,
                qo.getOrderBy());
        TermQueryBuilder termQueryBuilder = null;
        //国内 1
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_UN_ABROAD){
            termQueryBuilder = (QueryBuilders.termQuery("provinceId",qo.getTypeValue()));
        }
        //主题 2
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME){
            termQueryBuilder = QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }
        //国外 0
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD){
            termQueryBuilder = QueryBuilders.termQuery("countryId",qo.getTypeValue());
        }
        if(termQueryBuilder != null){
            return repository.search(termQueryBuilder,pageRequest);
        }
        else {
            return repository.findAll(pageRequest);
        }
    }

    @Override
    public List<StrategyTemplate> findStrategysByDestName(String keyword) {
        return repository.findByDestName(keyword);
    }


    private List<StatisVO> statisVOSGroup(String fieldId,String fieldName,String groupName,BoolQueryBuilder query){
        List<StatisVO> list = new ArrayList<>();
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder sourceId = new TermsValuesSourceBuilder("id");
        sourceId.field(fieldId);
        TermsValuesSourceBuilder sourceName = new TermsValuesSourceBuilder("name");
        sourceName.field(fieldName);
        sources.add(sourceId);
        sources.add(sourceName);
        CompositeAggregationBuilder compositeAggregationBuilder = new CompositeAggregationBuilder(groupName,sources);
        builder.addAggregation(compositeAggregationBuilder);
        if(query != null){
            builder.withQuery(query);
        }

        builder.withPageable(PageRequest.of(0,1));
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>)repository.search(builder.build());
        //Aggregation themeGroup = search.getAggregations().get("themeGroup");
        InternalComposite themeGroup = search.getAggregations().get(groupName);

        StatisVO vo = null;
        //List<InternalComposite.InternalBucket> buckets = themeGroup.getBuckets();
        //遍历出来再拿父类来替换
        for (CompositeAggregation.Bucket bucket : themeGroup.getBuckets()) {
            long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            long count = bucket.getDocCount();
            vo = new StatisVO(id,name,count);
            list.add(vo);
        }
        //优化一:倒序
        //1:按关联目的地的数量多少排序
        //排序结果int 类型:
        //大于0:大于  小于0:小于  等于0:等于
        Collections.sort(list, new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });
        return list;
    }

    private List<StatisVO> getDests(Long id){
        List<StrategyTemplate> list = repository.findDestsByThemeId(id);
        List<StatisVO> vos = new ArrayList<>();
        //优化二:去重
        List<String> name = new ArrayList<>();
        for (StrategyTemplate strategyTemplate : list) {
            if(!name.contains(strategyTemplate.getDestName())){
                StatisVO vo = new StatisVO();
                vo.setId(strategyTemplate.getDestId());
                vo.setName(strategyTemplate.getDestName());
                vos.add(vo);
                name.add(strategyTemplate.getDestName());
            }

        }
        return vos;
    }
}
